/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package br.com.loveprog.dao.impl;

import br.com.loveprog.dao.DaoGenerico;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author Leandro
 */
@Transactional(readOnly=true, propagation= Propagation.REQUIRED)
public class DaoGenericoImp<T, ID extends Serializable> implements DaoGenerico<T, ID> {
    private EntityManager entityManager;

    private final Class<T> oClass;

    public Class<T> getObjectClass() {
       return this.oClass;
    }

    @SuppressWarnings("unchecked")
    @PersistenceContext
    public void setEntityManager(EntityManager em){
        this.entityManager = em;
    }

    protected EntityManager getEntityManager(){
        if (entityManager ==  null)
            throw new IllegalStateException("Ërro");
        return entityManager;
    }
    @SuppressWarnings("unchecked")
    public DaoGenericoImp(){
        //determina através do argumento genérico T
        //a classe que será utilizada para o DAO
        this.oClass = (Class<T>)
        ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }


    @Override
    public T salvar(T object) {
        getEntityManager().clear();
        getEntityManager().persist(object);
        return object;
    }

    @Override
    public T pesquisarPorId(ID id) {
        return (T) getEntityManager().find(oClass, id);
    }

    @Override
    @Transactional(readOnly=false, propagation= Propagation.REQUIRED)
    public T atualizar(T object) {
        getEntityManager().merge(object);
        return object;
    }

    @Override
    @Transactional(readOnly=false, propagation= Propagation.REQUIRED)
    public void excluir(T object) {
        object = getEntityManager().merge(object);
        getEntityManager().remove(object);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<T> todos() {
        String queryS = "SELECT obj FROM " + oClass.getSimpleName() + " obj";
        Query query = getEntityManager().createQuery(queryS);
        return query.getResultList();
    }

    @SuppressWarnings("unchecked")
    public List<T> listPesqParam(Query q, Map<String, Object> params) {
     //   Query q = getEntityManager().createQuery(query);

        //separa os parametros transmitidos
        for(String chave: params.keySet()){
            q.setParameter(chave, params.get(chave));
        }
        return q.getResultList();
    }

    @SuppressWarnings("unchecked")
    public List<T> listPesq(Query q) {
       //Query q = getEntityManager().createQuery(query);
       return q.getResultList();
    }

    @SuppressWarnings("unchecked")
    public T pesqParam(Query q, Map<String, Object> params) {
      //  Query q = getEntityManager().createQuery(query);

        //separa os parametros transmitidos
        for(String chave: params.keySet()){
            q.setParameter(chave, params.get(chave));
        }

        try{
            return (T) q.getSingleResult();
        }catch(NoResultException nre){ //casso não haja resultados
            return null;
        }

    }

}
